#pragma once

#include "fxcc/core/graph/common/pch.h"
#include "fxcc/core/graph/common/Vertex.h"

namespace fxcc
{
    namespace graph
    {
        namespace common
        {


            struct FXCC_API     GeometryData
            {
                std::vector<glm::vec3> vertices;
                std::vector<glm::vec3> normals;
                std::vector<glm::vec2> texcoords;
                std::vector<glm::vec3> tangents;
                std::vector<glm::vec3> bigTangents;

                std::vector<uint32_t> indices32;
                
                void Inject(int index, VertexFixed& v)const;

                struct Header {
                    unsigned int numVertcies{ 0 };
                    unsigned int numNormals{ 0 };
                    unsigned int numTexCoords{ 0 };
                    unsigned int numTangents{ 0 };
                    unsigned int numBigTangents{ 0 };
                    unsigned int numIndices{ 0 };
                };

                Header GetHeader() const;

                bool ResizeHeader(const Header& header);

                void ResizeVertices(unsigned int numVertices)
                {
                    vertices.resize(numVertices);
                    normals.resize(numVertices);
                    texcoords.resize(numVertices);
                    tangents.resize(numVertices);
                    bigTangents.resize(numVertices);
                }

                void Resize32(unsigned int numVertices, unsigned int numIndices) {
                    ResizeVertices(numVertices);
                    indices32.resize(numIndices);
                }
                void Clear()
                {
                    vertices = {};
                    normals = {};
                    texcoords = {};
                    tangents = {};
                    bigTangents = {};
                }


                static GeometryData SubMeshData32(const std::vector<GeometryData>& meshDatas)
                {
                    GeometryData res;
                    for (const auto& meshData : meshDatas)
                    {
                        // calculate current vertices num
                        int indexOffset = res.vertices.size();


                        res.vertices.insert(res.vertices.end(), meshData.vertices.begin(), meshData.vertices.end());
                        res.normals.insert(res.normals.end(), meshData.normals.begin(), meshData.normals.end());
                        res.texcoords.insert(res.texcoords.end(), meshData.texcoords.begin(), meshData.texcoords.end());
                        res.tangents.insert(res.tangents.end(), meshData.tangents.begin(), meshData.tangents.end());
                        res.bigTangents.insert(res.bigTangents.end(), meshData.bigTangents.begin(), meshData.bigTangents.end());

                        auto& indices = res.indices32;
                        const auto& targetIndices = meshData.indices32;

                        for (auto& index : targetIndices)
                        {
                            indices.push_back(index + indexOffset);
                        }
                    }

                    return res;
                }

                void Write(std::ofstream& ofs) const;
                bool WriteToFile(const std::string& path) const;

                bool ReadFromFile(const std::string& path);
                bool Read(std::ifstream& ifs);

            };
        }
    }
}
